package com.dream.technology.components.context;

import com.alibaba.fastjson.JSONObject;
import com.dream.technology.db.entity.RcborrowingSnapshot;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 描述：
 *
 * @author chen_q_i@163.com
 * 2018/12/25 : 16:53.
 * @version : 1.0
 */
public class FlowContext {


    public volatile boolean stopFlow = false;
    private Map<String, Object> flowScopeDataHolder = new ConcurrentHashMap<String, Object>();
    private List<String> serviceNames = new ArrayList<>();

    public final static String application = "application";

    /**
     * 保存用户 ,订单 ,三方返回信息 ,以map形式存储
     */
    public final static String FLOW_DATA = "flowData";
    public final static String CUSTOMER = "customer"; // 用户
    public final static String CUSTOMER_ID = "customer.id"; // 用户
    public final static String ORDERFORM = "orderForm";// 订单
    public final static String ORDERFORM_ID = "orderForm.orderId";// 订单
    public final static String ORDERFORM_PRODUCT_CODE = "orderForm.productCode"; // 产品编码
    public final static String BASICINFO = "basicInfo"; // 产品编码
    public final static String LINKMAN = "linkMan"; // 联系人
    public final static String IDCARD = "idCard"; // 身份证号
    public final static String BANKCARD = "bankCard"; // 银行卡
    public final static String AUTHORIZATIONSTATUS = "authorizationStatus"; // 授信
    public final static String IDFACE = "idFace"; // 人脸认证
    public final static String CARDNUMBER = "customer.cardNumber"; // 身份证号码


    /**
     * 保存请求信息 请求过字段对应的service名称 list  数据放在flow data中 防止重复请求
     */
    public final static String SERVICE_NAMES = "serviceNames";
    /**
     * 初始化数据区 现在可能是用户表单和用户基本信息
     */
    public final static String initialInput = "initialInput";


    public final static String START_DATE = "startDate";
    public static final String EN_TIME = "endTime";
    /**
     * 流程中的规则描述 决定流程的执行顺序
     */
    public static final String FLOW_RULE = "FLOW_RULE";


    private RcborrowingSnapshot snapshot;

    /**
     * 用来保存三方数据
     *
     * @param serviceName
     * @param value
     */
    public void putService(String serviceName, Object value) {
        flowScopeDataHolder.put(serviceName, value);
    }

    public Object getService(String serviceName) {

        return get(serviceName);
    }

    /**
     * @param value 保存业务或外部系统初始输入的数据
     */
    public void putInitialInput(Map<String, Object> value) {
        flowScopeDataHolder.put(initialInput, value);
    }

    public Map<String, Object> getInitialInput() {
        return (Map<String, Object>) get(initialInput);
    }


    /**
     * 获取流程中数据容器
     *
     * @return
     */
    public Map<String, Object> getFlowData(String key) {
        Map<String, Object> flowData;
        flowData = (Map<String, Object>) flowScopeDataHolder.get(FLOW_DATA);
        if (flowData == null) {
            flowData = new HashMap<>();
            flowScopeDataHolder.put(FLOW_DATA, flowData);
        }
        return (Map<String, Object>) flowData.get(key);
    }


    /**
     * 放入 流程数据容器
     *
     * @return
     */
    public void putFlowData(String key, Object vaule) {
        Map<String, Object> flowData = (Map<String, Object>) flowScopeDataHolder.get(FLOW_DATA);
        flowData.put(key, vaule);
        flowScopeDataHolder.put(FLOW_DATA, flowData);

    }

    /**
     * 获取已处理的service name
     *
     * @return
     */
    public List<String> getServiceNames() {

        return serviceNames;
    }

    // josn 化使用
    public Map<String, Object> getFlowScopeDataHolder() {
        return flowScopeDataHolder;
    }

    /**
     * 添加已处理的service name
     *
     * @param serviceName
     */
    public void putServiceNames(String serviceName) {
//        List<String> serviceNames = getServiceNames();
        serviceNames.add(serviceName);

    }


    public void putStartDate() {
        flowScopeDataHolder.put(START_DATE, new Date());
    }

    public Date getStartDate() {
        return (Date) flowScopeDataHolder.get(START_DATE);
    }

    public Date getEnTime() {
        return (Date) flowScopeDataHolder.get(EN_TIME);
    }

    public void putEnTime() {
        flowScopeDataHolder.put(EN_TIME, new Date());
    }

    public String getFlowRule() {

        return (String) flowScopeDataHolder.get(FLOW_RULE);
    }

    public void setFlowRule(String flowRule) {

        flowScopeDataHolder.put(FLOW_RULE, flowRule);

    }


    public RcborrowingSnapshot getSnapshot() {
        return snapshot;
    }

    public void setSnapshot(RcborrowingSnapshot snapshot) {
        this.snapshot = snapshot;
    }

    public void put(String key, Object objectMap) {
        flowScopeDataHolder.put(key, objectMap);
    }

    public void putAll(Map<String, Object> map) {
        //剔除值为空的元素
        Map<String, Object> collect = map.entrySet().stream().filter(e -> e.getValue() != null).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        flowScopeDataHolder.putAll(collect);
    }

    /**
     * name
     *
     * @param dotProp ，可采用点句法的属性名
     * @return 获取任何属性的值或对象，从已经得到的任何数据中
     */
    public Object get(String dotProp) {
        if (dotProp == null) {
            return null;
        }
        int p = dotProp.indexOf(".");
        String key = null;
        if (p >= 0) {
            key = dotProp.substring(0, p);
        } else {
            key = dotProp;
            return flowScopeDataHolder.get(key);
        }
        String[] sa = dotProp.split("\\.");
        return _drillNew(flowScopeDataHolder, sa, 0);
    }

    public boolean isStopFlow() {
        return stopFlow;
    }

    public void stopFlow() {
        this.stopFlow = true;
    }

    public void passFlow() {
        this.stopFlow = false;
    }

    /**
     * 句点条件下递归获取
     *
     *  a.b.c
     * @param collec
     * @param keys
     * @param index
     * @return
     */

    private Object _drillNew(Object collec, String[] keys, int index) {

        if (collec == null) {
            return null;
        }
        if (keys == null) {
            return null;
        }

        try {

            Object obj = null;
            String key = keys[index].trim();
            if (collec instanceof List) {

                List collec_new = (List) collec;
                //如果是list解析
                if (key.startsWith("[") && key.endsWith("]")) {
                    key = key.substring(1, key.length() - 1).trim();
                    if (key.startsWith("(") && key.endsWith(")")) {
                        int sequence = Integer.parseInt(key.substring(1, key.length() - 1).trim());
                        if (sequence >= collec_new.size()) {
                            obj = null;
                        } else {
                            obj = collec_new.get(sequence);
                        }
                    } else if (key.contains("=")) {
                        String[] keyAndVal = key.split("=");
                        for (Object one_obj : collec_new) {
                            Map map_obj = (Map) one_obj;
                            if (String.valueOf(map_obj.get(keyAndVal[0].trim())).equals(keyAndVal[1].trim())) {
                                obj = map_obj;
                                break;
                            }

                        }
                    } else {
                        //默认为数组的解析
                        List aList = new ArrayList();
                        for (Object one_obj : collec_new) {
                            Map map_obj = (Map) one_obj;
                            aList.add(map_obj.get(key));

                        }
                        obj = aList;
                    }
                }
            } else if (collec instanceof JSONObject) {
                obj = ((JSONObject) collec).get(key);
            } else {
                //类似原来的代码的map正常处理
                obj = ((Map) collec).get(key);
            }

            if (index == keys.length - 1) {

                return obj;
            } else {
                if (null == obj) {
                    return null;
                }
                return _drillNew(obj, keys, index + 1);
            }
        } catch (Exception e) {
            //Console.info(FlowContext.class, "get method meet an error : " + e.getMessage());
            return null;
        }

    }


}
